package com.gjy.concurrency.aotmic;

import com.gjy.util.ThreadUtil;
import org.junit.jupiter.api.Test;

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.*;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-02-03 15:52:43
 */
public class Atomic2Test {

    @Test
    public void test10() {
        AtomicReferenceFieldUpdater<AtomicEntity, String> updater =
                AtomicReferenceFieldUpdater.newUpdater(AtomicEntity.class, String.class, "name");

        AtomicEntity entity = new AtomicEntity();
        updater.set(entity, "Hello");

        System.out.println("entity = " + entity);

        AtomicReferenceFieldUpdater<AtomicEntity, Integer> age =
                AtomicReferenceFieldUpdater.newUpdater(AtomicEntity.class, Integer.class, "age");
        age.set(entity, 11);
        System.out.println("entity = " + entity);
    }

    @Test
    public void test9() {
        AtomicEntity entity = new AtomicEntity();
        AtomicReference<AtomicEntity> reference = new AtomicReference<>(entity);
        System.out.println("reference.get() = " + reference.get());
    }

    @Test
    public void test8() {
        AtomicEntity entity = new AtomicEntity();
        AtomicStampedReference<AtomicEntity> reference
                = new AtomicStampedReference<>(entity, 1);

        reference.attemptStamp(entity, 2);

        System.out.println("reference.getStamp() = " + reference.getStamp());
    }

    @Test
    public void test7() {
        AtomicEntity entity = new AtomicEntity();
        AtomicMarkableReference<AtomicEntity> reference =
                new AtomicMarkableReference<>(entity, true);

        new Thread(() -> {
            if (reference.isMarked()) {
                System.out.println(entity);
            } else {
                System.out.println(Thread.currentThread().getName() + ":false");
            }
        }).start();

        new Thread(() -> {
            if (reference.isMarked()) {
                reference.set(entity, false);
                System.out.println(Thread.currentThread().getName() + ":false");
            } else {
                System.out.println(Thread.currentThread().getName() + ":true");
            }
        }).start();

    }

    @Test
    public void test6() {
        AtomicIntegerFieldUpdater<AtomicEntity> updater =
                AtomicIntegerFieldUpdater.newUpdater(AtomicEntity.class, "id");
        AtomicEntity atomicEntity = new AtomicEntity();
        updater.getAndSet(atomicEntity, 10);

        System.out.println("atomicEntity.id = " + atomicEntity.id);
    }

    @Test
    public void test5() {
        AtomicIntegerArray array = new AtomicIntegerArray(10);
        System.out.println("array.get(0) = " + array.get(1));
    }

    @Test
    public void test4() {
        AtomicBoolean ab = new AtomicBoolean();
        for (int i = 0; i < 100; i++) {
            new Thread(() -> ab.compareAndSet(false, true)).start();
            new Thread(() -> System.out.println("ab = " + ab)).start();
        }
    }

    @Test
    public void test3() {
//        LongAccumulator accumulator = new LongAccumulator(Long::sum, 0);
        LongAccumulator accumulator = new LongAccumulator(Long::sum, 0);
        ThreadPoolExecutor pool = ThreadUtil.defaultPool();
        for (int i = 1; i <= 100000; i++) {
            int finalI = i;
            pool.execute(() -> accumulator.accumulate(finalI));
        }
        System.out.println("accumulator = " + accumulator);
    }

    @Test
    public void test2() {
        AtomicInteger integer = new AtomicInteger();
        ThreadPoolExecutor pool = ThreadUtil.defaultPool();
        for (int i = 1; i <= 100000; i++) {
            pool.execute(integer::getAndIncrement);
        }
        System.out.println("integer = " + integer);
    }

    @Test
    public void test1() {
        LongAdder longAdder = new LongAdder();

        ThreadPoolExecutor pool = ThreadUtil.defaultPool();
        for (int i = 1; i <= 100000; i++) {
            pool.execute(longAdder::increment);
        }
        System.out.println("longAdder = " + longAdder);
    }
}
